gtk: Add a GTK_STATE_FLAG_WINDOW_UNFOCUSED widget state flag
authorRui Matos <tiagomatos@gmail.com>
Fri, 28 Oct 2011 22:45:38 +0000 (23:45 +0100)
committerRui Matos <tiagomatos@gmail.com>
Tue, 8 Nov 2011 19:33:22 +0000 (19:33 +0000)
This allows themes to style widgets differently according to whether the
toplevel window they are in is presented as focused.

https://bugzilla.gnome.org/show_bug.cgi?id=661428

gtk/gtkcssprovider.c
gtk/gtkcssselector.c
gtk/gtkenums.h
gtk/gtkwidget.c
gtk/gtkwindow.c

index 555a4b523b6adec598f3a25c80ce575662ff93be..839fa7c59674c1ff904333a9a4c04980a3a13202 100644 (file)
@@ -2007,6 +2007,7 @@ parse_selector_pseudo_class (GtkCssScanner  *scanner,
     { "inconsistent", 0, GTK_STATE_FLAG_INCONSISTENT },
     { "focused",      0, GTK_STATE_FLAG_FOCUSED },
     { "focus",        0, GTK_STATE_FLAG_FOCUSED },
+    { "window-unfocused", 0, GTK_STATE_FLAG_WINDOW_UNFOCUSED },
     { NULL, }
   }, nth_child_classes[] = {
     { "first",        GTK_REGION_FIRST, 0 },
index 2abe0923a7d5f3291253d89f0f2363ee83037416..b3ccb44e47e2655c15f13b81975aa1f13a0eae99 100644 (file)
@@ -153,7 +153,8 @@ _gtk_css_selector_print (const GtkCssSelector *selector,
         "selected",
         "insensitive",
         "inconsistent",
-        "focus"
+        "focus",
+        "window-unfocused"
       };
       guint i;
 
index dbc0e90ea09807e78590f1e5707a12f31f55edf2..7045f922c248a4180eebed31786218b2f2886846 100644 (file)
@@ -842,6 +842,7 @@ typedef enum
  * @GTK_STATE_FLAG_INSENSITIVE: Widget is insensitive.
  * @GTK_STATE_FLAG_INCONSISTENT: Widget is inconsistent.
  * @GTK_STATE_FLAG_FOCUSED: Widget has the keyboard focus.
+ * @GTK_STATE_FLAG_WINDOW_UNFOCUSED: Widget's toplevel window is unfocused.
  *
  * Describes a widget state.
  */
@@ -853,7 +854,8 @@ typedef enum
   GTK_STATE_FLAG_SELECTED     = 1 << 2,
   GTK_STATE_FLAG_INSENSITIVE  = 1 << 3,
   GTK_STATE_FLAG_INCONSISTENT = 1 << 4,
-  GTK_STATE_FLAG_FOCUSED      = 1 << 5
+  GTK_STATE_FLAG_FOCUSED      = 1 << 5,
+  GTK_STATE_FLAG_WINDOW_UNFOCUSED = 1 << 6
 } GtkStateFlags;
 
 /**
index b481f927d0018dd5e3b08294b9803fc0e361a40e..49e28fbf408447fe7fb6bbc6cf52690b99ef9ae7 100644 (file)
 
 #define WIDGET_CLASS(w)         GTK_WIDGET_GET_CLASS (w)
 
+#define GTK_STATE_FLAGS_BITS 7
+
 struct _GtkWidgetPrivate
 {
-  /* The state of the widget. There are actually only
-   * 5 widget states (defined in "gtkenums.h")
-   * so 3 bits.
+  /* The state of the widget. Needs to be able to hold all GtkStateFlags bits
+   * (defined in "gtkenums.h").
    */
-  guint state_flags : 6;
+  guint state_flags : GTK_STATE_FLAGS_BITS;
 
   guint direction             : 2;
 
@@ -529,7 +530,7 @@ enum {
 
 struct _GtkStateData
 {
-  guint         flags : 6;
+  guint         flags : GTK_STATE_FLAGS_BITS;
   guint         operation : 2;
   guint                use_forall : 1;
 };
index 25a5f9f07601e5cb88e82baed3d8ae3c8d12e77f..0d245b3e2ca7e68f8d2efcec9b89dadc3e94065b 100644 (file)
@@ -474,6 +474,8 @@ static void gtk_window_get_preferred_height   (GtkWidget           *widget,
                                               gint                *minimum_size,
                                               gint                *natural_size);
 
+static void ensure_state_flag_window_unfocused (GtkWidget *widget);
+
 G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                gtk_window_buildable_interface_init))
@@ -4817,6 +4819,8 @@ gtk_window_map (GtkWidget *widget)
     gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
   else
     gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
+
+  ensure_state_flag_window_unfocused (widget);
 }
 
 static gboolean
@@ -5463,6 +5467,9 @@ gtk_window_state_event (GtkWidget           *widget,
 {
   update_grip_visibility (GTK_WINDOW (widget));
 
+  if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
+    ensure_state_flag_window_unfocused (widget);
+
   return FALSE;
 }
 
@@ -9618,3 +9625,21 @@ gtk_window_set_has_user_ref_count (GtkWindow *window,
 
   window->priv->has_user_ref_count = setting;
 }
+
+static void
+ensure_state_flag_window_unfocused (GtkWidget *widget)
+{
+  GdkWindow *window;
+  gboolean window_focused = TRUE;
+
+  window = gtk_widget_get_window (widget);
+
+  window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
+
+  if (!window_focused)
+    gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_WINDOW_UNFOCUSED, FALSE);
+  else
+    gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_WINDOW_UNFOCUSED);
+
+  gtk_widget_queue_draw (widget);
+}